package com.greate.shiro.springbootshirodemo.config;


import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.greate.shiro.springbootshirodemo.entity.SystemUser;
import com.greate.shiro.springbootshirodemo.service.SystemPermissionService;
import com.greate.shiro.springbootshirodemo.service.SystemRolePermissionService;
import com.greate.shiro.springbootshirodemo.service.SystemUserRoleService;
import com.greate.shiro.springbootshirodemo.service.SystemUserService;
import lombok.SneakyThrows;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * 自定义 授权 realm ， 登录使用
 *
 * @author Administrator
 */
@Component
public class CustomAuthorizingRealm extends AuthorizingRealm {

	@Resource
	private SystemUserService systemUserService;

	@Resource
	private SystemPermissionService systemPermissionService;

	@Resource
	private SystemRolePermissionService systemRolePermissionService;

	@Resource
	private SystemUserRoleService systemUserRoleService;

	@Override
	@SneakyThrows
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		String token = principals.getPrimaryPrincipal().toString();
		TokenInfo unSign = JwtTokenUtils.unsign(token, TokenInfo.class);

        /*
            查询对应的角色
         */
		assert unSign != null;
		List<String> rolesNameStringList = systemUserService.getRolesNameStringList(unSign.getUsername(), unSign.getPassword());
		authorizationInfo.addRoles(rolesNameStringList);

        /*
            查询对应的权限
         */
		Integer userIdByUsernameAndPassword = systemUserService.getUserIdByUsernameAndPassword(unSign.getUsername(), unSign.getPassword());
		List<Integer> rolesIdByUserId = systemUserRoleService.getRolesIdByUserId(userIdByUsernameAndPassword);
		List<Integer> permissionIdByRolesId = systemRolePermissionService.getPermissionIdByRolesId(rolesIdByUserId);
		List<String> permissionNameByRoleIds = systemPermissionService.getPermissionNameByPermissionIds(permissionIdByRolesId);
		authorizationInfo.addStringPermissions(permissionNameByRoleIds);
		return authorizationInfo;
	}

	/**
	 * 验证 token 是否正确 ， 是否有对应的用户
	 *
	 * @param token token
	 * @return SimpleAuthenticationInfo
	 */
	@Override
	@SneakyThrows
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		JwtToken myJwtToken = (JwtToken) token;
		String credentials = myJwtToken.getCredentials().toString();
		TokenInfo unSign = JwtTokenUtils.unsign(credentials, TokenInfo.class);
		assert unSign != null;
		SystemUser user = ChainWrappers.lambdaQueryChain(systemUserService.getBaseMapper())
			.eq(SystemUser::getUsername, unSign.getUsername())
			.eq(SystemUser::getPassword, unSign.getPassword())
			.last(" LIMIT 1")
			.one();
		if (user == null) {
			return null;
		}
		return new SimpleAuthenticationInfo(credentials, credentials, "customRealm");
	}

	/**
	 * 限定这个Realm只支持我们自定义的JWT Token
	 */
	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof JwtToken;
	}

}
